Skip to content

16 DOM 事件基础

事件

  • 事件是编程语言中的术语,它是用来描述程序的行为或状态的,一旦行为或状态发生改变,便立即调用一个函数。
  • 一般是指在网页中发生的交互事件,例如鼠标点击、键盘按键、页面加载等。
  • 例如:用户使用【鼠标点击】网页中的一个按钮、用户使用【鼠标拖拽】网页中的一张图片。
  • 以下是 HTML 中常见的事件:
    • onclick 事件:当用户点击 HTML 元素时触发,例如按钮、链接等。
    • onmouseover 事件:当用户将鼠标移动到 HTML 元素上时触发,例如图片、链接等。
    • onmouseout 事件:当用户将鼠标从 HTML 元素上移开时触发,例如图片、链接等。
    • onkeydown 事件:当用户按下键盘上的任意键时触发,例如输入框等。
    • onload 事件:当页面加载完成时触发,例如图片、音频、视频等。
    • onsubmit 事件:当用户提交表单时触发,例如登录、注册等。
    • onscroll 事件:当用户滚动页面时触发,例如滚动条等。
    • onresize 事件:当用户改变浏览器窗口大小时触发,例如响应式网页设计等。

事件监听(绑定)

  1. 什么是事件监听?

    • 就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件。
    • 元素对象.addEventListener("事件类型", 要执行的函数);
  2. 事件监听三要素是什么?

    • 事件源 (谁被触发了)
    • 事件类型 (用什么方式触发,点击还是鼠标经过等)
    • 事件处理程序(要做什么事情)

事件监听

  • 事件监听是指在某个 HTML 元素上绑定一个特定的事件,当该元素发生该事件时,执行预先定义好的 JavaScript 代码。
  • 让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 绑定事件或者注册事件。
  • 比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等。
  • 结合 DOM 使用事件时,需要为 DOM 对象添加事件监听,等待事件发生(触发)时,便立即调用一个函数。
  • addEventListener() 是 DOM 对象专门用来添加事件监听的方法,它的两个参数分别为【事件类型】和【事件回调】,该方法接受三个参数:
    • 事件类型:指定要监听的事件类型,比如 clickmouseoverkeydown 等。
    • 回调函数:当事件被触发时要执行的 JavaScript 代码。
    • 是否捕获:一个可选的布尔值,表示事件是否应该在捕获阶段被处理。
js
元素对象.addEventListener("事件类型", 要执行的函数);

完成事件监听步骤

  1. 获取 DOM 元素
  2. 通过 addEventListener 方法为 DOM 节点添加事件监听
  3. 等待事件触发,如用户点击了某个按钮时便会触发 click 事件类型
  4. 事件触发后,相对应的回调函数会被执行

大白话描述:所谓的事件无非就是找个机会(事件触发)调用一个函数(回调函数)。

事件监听三要素

  • 事件源:那个 dom 元素被事件触发了,要获取 dom 元素。
  • 事件类型:用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等。
  • 事件调用的函数:要做什么事。
html
<button id="myButton">Click me</button>

<script>
  const button = document.querySelector("#myButton");
  // 使用了 addEventListener() 方法来将一个点击事件监听器添加到按钮上。
  // 当用户点击按钮时,会触发回调函数中的代码,输出 "Button clicked!" 到控制台。
  button.addEventListener("click", function () {
    console.log("Button clicked!");
  });
</script>

注意

  1. 事件类型要加引号。
  2. 函数是点击之后再去执行,每次点击都会执行一次。
案例练习 - 京东点击关闭顶部广告

京东点击关闭顶部广告 (codepen.io)

  • 需求:点击关闭之后,顶部关闭
  • 分析:
    • 点击的是关闭按钮
    • 关闭的是父盒子
  • 核心:利用样式的显示和隐藏完成, display:none 隐藏元素 display:block 显示元素
html
<header>
  <div class="ad">
    <img
      src="https://img14.360buyimg.com/cms/jfs/t1/31138/39/20627/7102/643df622F6af8d366/a8552639ef51211f.jpg"
      alt="广告图片"
      referrerpolicy="no-referrer" />
    <button class="close">关闭</button>
  </div>
  <nav>
    <ul>
      <li>首页</li>
      <li>分类</li>
      <li>购物车</li>
      <li>我的</li>
    </ul>
  </nav>
</header>
css
header {
  position: relative;
}

.ad {
  position: relative;
  height: 110px;
  background-color: #f5f5f5;
  display: block;
}

.ad img {
  display: block;
  width: 235px;
  height: 110px;
  margin: 0 auto;
}

.ad .close {
  position: absolute;
  top: 5px;
  right: 5px;
}

nav {
  height: 50px;
  line-height: 50px;
  background-color: #333;
  color: #fff;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: space-around;
  align-items: center;
  font-size: 24px;
}
js
const closeBtn = document.querySelector(".ad .close");
const adBox = document.querySelector(".ad");

closeBtn.addEventListener("click", function () {
  adBox.style.display = "none";
});
案例练习 - 随机点名案例

随机点名案例 (codepen.io)

  • 分析:
    • 点击开始按钮随机抽取数组的一个数据,放到页面中
    • 点击结束按钮删除数组当前抽取的一个数据
    • 当抽取到最后一个数据的时候,两个按钮同时禁用(写点开始里面,只剩最后一个数据不用抽了)
  • 核心:利用定时器快速展示,停止定时器结束展示
html
<div class="container">
  <h1>随机点名</h1>
  <label for="name"
    >当前被点名的人员:
    <input type="text" id="name" readonly="readonly" />
  </label>
  <div class="btn">
    <button id="start">开始</button>
    <button id="stop">结束</button>
  </div>
</div>
css
.container {
  display: flex;
  flex-direction: column;
  align-items: center;

  margin: 50px auto;
  width: 500px;
  height: 300px;
  border: 1px solid #ccc;
  border-radius: 10px;
  line-height: 60px;
  background-color: #69d2e7;
}

input {
  width: 200px;
  height: 30px;
  border: none;
  border-radius: 5px;
  background-color: #fff;
  text-align: center;

  font-size: 22px;
  font-weight: 600;
}

.btn {
  display: flex;
  justify-content: space-around;
  width: 400px;
  margin-top: 50px;
}

button {
  width: 80px;
  height: 30px;
  line-height: 30px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}
js
// 定义需要点名的人员名单
const arr = ["马超", "黄忠", "赵云", "关羽", "张飞"];
console.log(arr);

// 获取页面元素
const startBtn = document.querySelector("#start");
const stopBtn = document.querySelector("#stop");
const nameInput = document.querySelector("#name");

// 定义变量
let currentIndex = 0; // 当前被点名的人员在数组中的下标
let timer = 0; // 定时器

// 随机获取数组中的一个元素
function getRandomItem(arr) {
  const index = Math.floor(Math.random() * arr.length);
  return arr[index];
}

// 点击开始按钮
// startBtn.onclick = function () {
startBtn.addEventListener("click", function () {
  // 启动定时器
  timer = setInterval(function () {
    // 获取随机元素
    const item = getRandomItem(arr);
    // 将元素展示在文本框中
    nameInput.value = item;
  }, 100);

  // 如果数组中只剩下最后一个元素,禁用开始和结束按钮
  if (arr.length === 1) {
    // startBtn.disabled = true;
    // stopBtn.disabled = true;
    startBtn.disabled = stopBtn.disabled = true;
  }
});

// 点击结束按钮
stopBtn.onclick = function () {
  // 停止定时器
  clearInterval(timer);
  // 将当前被点名的人员从数组中删除
  arr.splice(currentIndex, 1);
  console.log(arr);
};

事件监听版本

  • DOM L0:事件源.on事件 = function() {}
  • DOM L2:事件源.addEventListener(事件, 事件处理函数)
  • 区别:on 方式会被覆盖,addEventListener 方式可绑定多次,拥有事件更多特性,推荐使用。
  • 发展史:
    • DOM L0:是 DOM 的发展的第一个版本;L:level
    • DOM L1:DOM 级别 1 于 1998 年 10 月 1 日成为 W3C 推荐标准
    • DOM L2:使用 addEventListener 注册事件
    • DOM L3:DOM3 级事件模块在 DOM2 级事件的基础上重新定义了这些事件,也添加了一些新事件类型

事件类型

事件类型指的是用户与网页交互时所触发的事件,如鼠标点击、键盘按键、窗口大小改变等。

  • 鼠标事件:当用户使用鼠标与页面交互时,会触发鼠标事件。常见的鼠标事件包括:click(点击)、dbclick(双击)、mousedown(鼠标按下)、mouseup(鼠标松开)、mousemove(鼠标移动)、mouseover(鼠标移入)、mouseout(鼠标移出)等。
  • 键盘事件:当用户使用键盘与页面交互时,会触发键盘事件。常见的键盘事件包括:keydown(键按下)、keyup(键松开)、keypress(键按下并松开)等。
  • 表单事件:当用户与表单元素交互时,会触发表单事件。常见的表单事件包括:submit(提交表单)、reset(重置表单)、change(表单元素值改变)、focus(表单元素获得焦点)、blur(表单元素失去焦点)等。
  • 窗口事件:当浏览器窗口发生变化时,会触发窗口事件。常见的窗口事件包括:load(页面加载完成)、unload(页面关闭)、resize(窗口大小改变)、scroll(滚动条滚动)等。
  • 媒体事件:当用户与媒体(如音频、视频)交互时,会触发媒体事件。常见的媒体事件包括:play(媒体开始播放)、pause(媒体暂停)、ended(媒体播放结束)、timeupdate(媒体播放时间更新)等。
  • 触摸事件:当用户使用触摸屏设备与页面交互时,会触发触摸事件。常见的触摸事件包括:touchstart(手指触摸屏幕)、touchmove(手指在屏幕上滑动)、touchend(手指离开屏幕)等。

鼠标事件

鼠标事件是指用户在网页上使用鼠标进行交互时所触发的事件。常见的鼠标事件有以下几种:

  • click:鼠标单击事件,当用户单击鼠标时触发。
  • dblclick:鼠标双击事件,当用户双击鼠标时触发。
  • mousedown:鼠标按下事件,当用户按下鼠标时触发。
  • mouseup:鼠标松开事件,当用户松开鼠标时触发。
  • mousemove:鼠标移动事件,当用户移动鼠标时触发。
  • mouseover:鼠标移入事件,当用户将鼠标移动到某个元素上时触发。
  • mouseout:鼠标移出事件,当用户将鼠标移出某个元素时触发。
  • mouseenter:鼠标进入事件,当用户将鼠标移动到某个元素上时触发,与 mouseover 不同的是,mouseenter 不会冒泡。
  • mouseleave:鼠标离开事件,当用户将鼠标移出某个元素时触发,与 mouseout 不同的是,mouseleave 不会冒泡。
  • mousewheel:鼠标滚轮事件,当用户使用鼠标滚轮时触发。

对于以上鼠标事件,可以通过 addEventListener 方法来为元素添加事件监听器。

js
const element = document.getElementById("myElement");
element.addEventListener("click", function () {
  console.log("clicked");
});

在事件监听器中,可以通过 event 对象来获取事件的相关信息。在事件处理程序中,可以访问事件对象,该对象提供与事件相关的信息,例如鼠标位置和按钮状态。

js
element.addEventListener("mousemove", function (event) {
  console.log("mouse X:", event.clientX);
  console.log("mouse Y:", event.clientY);
});

有时需要在鼠标事件中取消默认行为,例如防止上下文菜单的出现。可以通过在事件处理程序中调用 event.preventDefault() 方法来实现。

js
element.addEventListener("contextmenu", function (event) {
  event.preventDefault();
});

通过使用鼠标事件,可以实现各种交互效果,例如拖拽、点击、菜单等。

案例联系 - 轮播图点击切换

轮播图点击切换 (codepen.io)

  • 需求:当点击左右的按钮,可以切换轮播图
  • 分析:
    • 右侧按钮点击,变量 ++,如果大于等于 8,则复原 0
    • 左侧按钮点击,变量 --,如果小于 0,则复原最后一张
    • 鼠标经过暂停定时器
    • 鼠标离开开启定时器
html
<div class="carousel">
  <div class="carousel-container">
    <!-- <div class="carousel-item active">
        <img src="https://img1.baidu.com/it/u=1831000000,1831000000&fm=26&fmt=auto&gp=0.jpg" alt="" />
      </div> -->
  </div>
  <div class="carousel-footer">
    <div class="carousel-mask"></div>
    <div class="carousel-tool">
      <a href="https://www.bilibili.com/bangumi/play/ep743775" target="_blank" rel="noopener noreferrer">
        <span>XY 密室今日开业!游戏开始!</span>
      </a>
      <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
    </div>
    <div class="carousel-buttons">
      <button class="prev">&lt;</button>
      <button class="next">&gt;</button>
    </div>
  </div>
</div>
css
.carousel {
  width: 1000px;
  height: 630px;
  margin: 0 auto;
  overflow: hidden;
  position: relative;
}

.carousel .carousel-container {
  width: 100%;
  height: 550px;
  position: relative;
}

.carousel .carousel-container .carousel-item {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

.carousel .carousel-container .carousel-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.carousel .carousel-footer {
  width: 100%;
  height: 80px;
  position: relative;
  padding: 12px 12px 0 12px;
}

.carousel .carousel-footer .carousel-mask {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
}

.carousel .carousel-footer .carousel-tool a {
  margin: 0;
  color: #fff;
  font-size: 18px;
  margin-bottom: 10px;
  text-decoration: none;
}

.carousel .carousel-footer .carousel-tool a:hover {
  text-decoration: underline;
}

.carousel .carousel-footer .carousel-tool ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

.carousel .carousel-footer .carousel-tool ul li {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #fff;
  margin: 10px 5px 0 5px;

  opacity: 0.4;
  cursor: pointer;
}

.carousel .carousel-footer .carousel-tool ul li.active {
  width: 12px;
  height: 12px;
  opacity: 1;
  /* background-color: #ff0000; */
}

.carousel .carousel-footer .carousel-buttons {
  position: absolute;
  right: 0;
  top: 12px;
  display: flex;
}

.carousel .carousel-footer .carousel-buttons button {
  width: 30px;
  height: 30px;
  margin-right: 40px;
  border-radius: 5px;
  border: none;
  background-color: rgba(255, 255, 255, 0.1);
  color: #fff;
  font-size: 20px;
  cursor: pointer;
  outline: none;
}

.carousel .carousel-footer .carousel-buttons button:hover {
  background-color: rgba(255, 255, 255, 0.2);
}
js
const sliderData = [
  {
    url: "https://s2.loli.net/2023/04/27/KPwgoASjN8r6WQh.webp",
    title: "对人类来说会不会太超前了?",
    color: "rgb(100, 67, 68)",
  },
  {
    url: "https://s2.loli.net/2023/04/27/Ml13notv94pIjQy.webp",
    title: "开启剑与雪的黑暗传说!",
    color: "rgb(43, 35, 26)",
  },
  {
    url: "https://s2.loli.net/2023/04/27/8Kxs6wQYcZnOGqk.webp",
    title: "真正的 jo 厨出现了!",
    color: "rgb(36, 31, 33)",
  },
  {
    url: "https://s2.loli.net/2023/04/27/WvoFmSe95VbPi1J.webp",
    title: "李玉刚:让世界通过 B 站看到东方大国文化",
    color: "rgb(139, 98, 66)",
  },
  {
    url: "https://s2.loli.net/2023/04/27/4KayHmQTZLhu8Fr.webp",
    title: "快来分享你的寒假日常吧~",
    color: "rgb(67, 90, 92)",
  },
  {
    url: "https://s2.loli.net/2023/04/27/vuXLiHplRzqsfFY.webp",
    title: "哔哩哔哩小年 YEAH",
    color: "rgb(166, 131, 143)",
  },
  {
    url: "https://s2.loli.net/2023/04/27/dsouL2A1qQD6K89.webp",
    title: "一站式解决你的电脑配置问题!!!",
    color: "rgb(53, 29, 25)",
  },
  {
    url: "https://s2.loli.net/2023/04/27/U8ifDI3mAaOTxG1.webp",
    title: "谁不想和小猫咪贴贴呢!",
    color: "rgb(99, 72, 114)",
  },
];

const sliderContainer = document.querySelector(".carousel .carousel-container");
let count = 0;

// 注册 next 点击事件
const next = document.querySelector(".next");
next.addEventListener("click", function () {
  count++;
  if (count >= sliderData.length) {
    count = 0;
  }

  // 调用复用函数
  toggle();
});

// 注册 prev 点击事件
const prev = document.querySelector(".prev");
prev.addEventListener("click", function () {
  count--;
  if (count < 0) {
    count = 7;
  }

  // 调用复用函数
  toggle();
});

// 复用函数
function toggle() {
  sliderContainer.innerHTML = "";
  let sliderItem = document.createElement("div");
  sliderItem.className = "carousel-item";
  sliderItemImg = document.createElement("img");
  sliderItemImg.src = sliderData[count].url;
  sliderItemImg.referrerpolicy = "no-referrer";
  sliderItem.appendChild(sliderItemImg);
  sliderContainer.appendChild(sliderItem);

  const sliderFooter = document.querySelector(".carousel .carousel-footer");
  sliderFooter.style.backgroundColor = sliderData[count].color;

  const sliderFooterTitle = document.querySelector(".carousel .carousel-footer .carousel-tool a span");
  sliderFooterTitle.innerText = sliderData[count].title;

  const sliderFooterUl = document.querySelector(".carousel .carousel-footer .carousel-tool ul");
  const sliderFooterLi = sliderFooterUl.querySelectorAll("li");
  sliderFooterLi.forEach((item, index) => {
    if (index === count) {
      item.classList.add("active");
    } else {
      item.classList.remove("active");
    }
  });
}

// 自动播放
let timer = setInterval(function () {
  next.click();
}, 1000);

// 鼠标经过盒子停止播放
const carousel = document.querySelector(".carousel");
carousel.addEventListener("mouseenter", function () {
  clearInterval(timer);
});

// 鼠标离开盒子继续播放
carousel.addEventListener("mouseleave", function () {
  timer = setInterval(function () {
    next.click();
  }, 1000);
});

键盘事件

键盘事件是指用户在键盘上按下或释放按键时触发的事件。常用的键盘事件包括键盘按下事件(keydown)、键盘释放事件(keyup)和键盘输入事件(keypress)。

  • 键盘按下事件 keydown:当用户按下键盘上的任意一个键时触发。keydown 事件在按键被按下的瞬间触发,而不是在按键被松开的瞬间触发。在用户长按某个键时,keydown 事件会重复触发。
  • 键盘释放事件 keyup:当用户释放键盘上的任意一个键时触发。keyup 事件在按键被松开的瞬间触发。
  • 键盘输入事件 keypress:当用户按下键盘上的字符键时触发。keypress 事件在按键被按下的瞬间触发,而不是在按键被松开的瞬间触发。keypress 事件只能检测字符键,不能检测功能键(如 ShiftCtrlAlt 等)和方向键(如上下左右箭头键)。

对于以上键盘事件,可以使用 addEventListener() 方法来为元素添加键盘事件监听器。

js
// 使用 addEventListener() 方法为 document 元素添加了三个键盘事件监听器,分别对应键盘按下、键盘释放和键盘输入事件
// 在事件处理函数中,可以通过 event 对象获取键盘事件的相关信息,如按下的键位、按键码等
document.addEventListener("keydown", function (event) {
  console.log("键盘按下:" + event.key);
});

document.addEventListener("keyup", function (event) {
  console.log("键盘释放:" + event.key);
});

document.addEventListener("keypress", function (event) {
  console.log("键盘输入:" + event.key);
});

焦点事件

焦点事件是指与 HTML 文档中的焦点相关的事件。焦点是指当前被选中的元素,可以通过鼠标或键盘来改变焦点。常见的焦点事件包括:

  • focus:当元素获得焦点时触发该事件。
  • blur:当元素失去焦点时触发该事件。
  • focusin:当元素或其子元素获得焦点时触发该事件。
  • focusout:当元素或其子元素失去焦点时触发该事件。

这些事件可以用于实现一些交互功能,例如在输入框获得焦点时自动弹出键盘,或者在表单提交前检查输入框是否为空等。

js
// <input type="text">

// 获取输入框元素
const input = document.querySelector("input");

// 绑定 focus 事件
input.addEventListener("focus", function () {
  console.log("输入框获得焦点");
});

// 绑定 blur 事件
input.addEventListener("blur", function () {
  console.log("输入框失去焦点");
});
案例联系 - 小米搜索框案例

小米搜索框 (codepen.io)

  • 需求:当表单得到焦点,显示下拉菜单,失去焦点隐藏下来菜单
  • 分析:
    • 开始下拉菜单要进行隐藏
    • 表单获得焦点 focus,则显示下拉菜单,并且文本框变色(添加类)
    • 表单失去焦点,反向操作
html
<div class="search">
  <input type="text" placeholder="请输入搜索关键词" />
  <ul>
    <li><a href="#">全部商品</a></li>
    <li><a href="#">小米 11</a></li>
    <li><a href="#">小米 10S</a></li>
    <li><a href="#">小米笔记本</a></li>
    <li><a href="#">小米手机</a></li>
    <li><a href="#">黑鲨 4</a></li>
    <li><a href="#">空调</a></li>
  </ul>
</div>
css
a {
  text-decoration: none;
  color: #555;
}

.search {
  position: relative;
  margin: 50px auto;
  width: 300px;
}

.search input[type="text"] {
  width: 100%;
  height: 40px;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 20px;
  font-size: 16px;
  outline: none;
  transition: all 0.3s ease-in-out;
}

.search input[type="text"].focus {
  border-color: #ff6700;
  box-shadow: 0 0 5px #ff6700;
}

.search ul {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 999;
  background: #fff;
  border: 1px solid #ccc;
  border-top: none;
  border-radius: 0 0 5px 5px;
  box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1);
  list-style: none;
  padding: 0;
  margin: 0;
  display: none;
}

.search li {
  padding: 10px;
  cursor: pointer;
}

.search li:hover {
  background: #f5f5f5;
}
js
const input = document.querySelector('.search input[type="text"]');
const ul = document.querySelector(".search ul");

input.addEventListener("focus", function () {
  ul.style.display = "block";
  input.classList.add("focus");
});

input.addEventListener("blur", function () {
  ul.style.display = "none";
  input.classList.remove("focus");
});

文本事件

文本事件是指在 HTML 文本元素(如文本框、文本域等)中发生的事件,这些事件可以被 JavaScript 监听和处理。常见的文本事件包括:

  • input 事件:当用户在一个可编辑的 HTML 元素中输入或粘贴文本时触发。该事件在文本框、文本域、富文本编辑器等元素中经常使用。
  • keydown 事件:当用户按下键盘上的任意键时触发。该事件可以用来捕获用户输入的文本内容。
  • keyup 事件:当用户释放键盘上的任意键时触发。该事件可以用来捕获用户输入的文本内容。
  • change 事件:当可编辑元素的内容发生变化时触发。该事件在文本框、下拉菜单等元素中经常使用。
  • select 事件:当用户选中文本时触发。该事件在文本框、文本域等元素中经常使用。
  • cutcopypaste 事件:当用户执行剪切、复制、粘贴操作时触发。这些事件可以用来监控用户对文本的操作并进行相应的处理。
  • compositionstartcompositionupdatecompositionend 事件:当用户输入非拉丁字符(如中文、日文、韩文等)时触发。这些事件可以用来处理非拉丁字符的输入和编辑。

这些事件可以通过 JavaScript 监听和处理,以实现一些交互效果,例如实时搜索、实时校验输入内容等。

js
// <input type="text" id="myInput">

const inputElement = document.getElementById("myInput");

// 使用 addEventListener 方法来监听 input 事件
// 当用户在 input 元素中输入或粘贴文本时,会触发该事件,并执行绑定的回调函数
inputElement.addEventListener("input", function (event) {
  // 获取 event.target.value 属性来获取用户输入的文本内容,然后进行相应的处理
  console.log("Input value changed:", event.target.value);
});
案例联系 - 评论字数统计
  • 需求:用户输入文字,可以计算用户输入的字数
  • 分析:
    • 判断用输入事件 input
    • 不断取得文本框里面的字符长度,文本域.value.length
    • 把获得数字给下面文本框
html
css
js

表单事件

表单事件是指在表单元素上发生的事件,如用户在输入框中输入字符、提交表单等操作。在 JavaScript 中,可以使用事件监听器来捕捉这些事件并执行相应的操作。

常见的表单事件包括:

  • onsubmit:当用户提交表单时触发。可以在该事件中验证表单数据的有效性,并阻止表单提交或执行提交操作。

    html
    <form onsubmit="return validateForm()">
      <input type="text" name="username" required />
      <input type="password" name="password" required />
      <button type="submit">Submit</button>
    </form>
    <script>
      function validateForm() {
        // 验证表单数据的有效性
        if (/* 验证不通过 */) {
          alert("Invalid input!");
          return false; // 阻止表单提交
        }
        // 验证通过,可以执行提交操作
        return true;
      }
    </script>
  • onreset:当用户重置表单时触发。可以在该事件中清空表单数据或执行其他操作。

    html
    <form onreset="clearForm()">
      <input type="text" name="username" />
      <input type="password" name="password" />
      <button type="reset">Reset</button>
    </form>
    <script>
      function clearForm() {
        // 清空表单数据或执行其他操作
        document.querySelector("input[name='username']").value = "";
        document.querySelector("input[name='password']").value = "";
      }
    </script>
  • onchange:当表单元素的值发生改变时触发。可以在该事件中根据用户输入的值进行相应的操作。

    html
    <input type="text" name="age" onchange="checkAge()" />
    <script>
      function checkAge() {
        // 根据用户输入的年龄进行相应的操作
        var age = parseInt(document.querySelector("input[name='age']").value);
        if (age < 18) {
          alert("You are too young!");
        } else {
          alert("Welcome!");
        }
      }
    </script>
  • onfocus:当表单元素获得焦点时触发。可以在该事件中执行一些初始化操作或显示提示信息。

    html
    <input type="text" name="username" onfocus="showHint()" />
    <div id="hint"></div>
    <script>
      function showHint() {
        // 显示提示信息
        document.getElementById("hint").innerHTML = "Please enter your username.";
      }
    </script>
  • onblur:当表单元素失去焦点时触发。可以在该事件中验证用户输入的值或隐藏提示信息。

    html
    <input type="text" name="email" onblur="validateEmail()" />
    <div id="error"></div>
    <script>
      function validateEmail() {
        // 验证用户输入的邮箱地址是否合法
        var email = document.querySelector("input[name='email']").value;
        if (!isValidEmail(email)) {
          document.getElementById("error").innerHTML = "Invalid email address!";
        } else {
          document.getElementById("error").innerHTML = "";
        }
      }
      function isValidEmail(email) {
        // 验证邮箱地址是否合法
        // ...
      }
    </script>
  • onkeydownonkeyuponkeypress:当用户在表单元素中按下或释放键盘上的按键时触发。可以在这些事件中捕捉用户的输入并执行相应的操作。

    html
    <input type="text" name="search" onkeydown="search(event)" />
    <script>
      function search(event) {
        // 捕捉用户输入的搜索关键词并执行搜索操作
        if (event.keyCode === 13) {
          var keyword = document.querySelector("input[name='search']").value;
          searchResults(keyword);
        }
      }
      function searchResults(keyword) {
        // 执行搜索操作
        // ...
      }
    </script>
  • onselect:当用户选择表单元素中的一段文本时触发。可以在该事件中获取用户选择的文本并执行相应的操作。

    html
    <input type="text" name="text" onselect="copyText()" />
    <script>
      function copyText() {
        // 复制用户选择的文本
        var selectedText = window.getSelection().toString();
        if (selectedText) {
          document.execCommand("copy");
          alert("Text copied to clipboard!");
        }
      }
    </script>

除了以上常见的表单事件,还有一些其他的事件,如 onloadonunload 等。在使用表单事件时,需要注意事件的兼容性和浏览器的差异性,以确保代码在各种浏览器中都能正常运行。

事件对象

  1. 事件对象是什么?

    • 也是个对象,这个对象里有事件触发时的相关信息
  2. 事件对象在哪里?

    • 在事件绑定的回调函数的第一个参数就是事件对象
    js
    元素.addEventListener("click", function (e) {}

获取事件对象

  • 事件对象是什么
    • 也是个对象,这个对象里有事件触发时的相关信息。
    • 例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息。
  • 使用场景
    • 可以判断用户按下哪个键,比如按下回车键可以发布新闻。
    • 可以判断鼠标点击了哪个元素,从而做相应的操作。
  • 获取事件对象
    • 在事件绑定的回调函数的第一个参数就是事件对象。
    • 一般命名为 eventeve
js
// 获取 .box 元素
const box = document.querySelector(".box");

// 添加事件监听
// e 为事件对象
box.addEventListener("click", function (e) {
  console.log("任意事件类型被触发后,相关信息会以对象形式被记录下来...");

  // 事件回调函数的第 1 个参数即所谓的事件对象
  console.log(e);
});

事件对象常用属性

  • event.type

    获取当前的事件类型,例如 "click"、"keydown"、"mousemove" 等常见事件。

    js
    // <button id="myButton">Click me</button>
    
    // 获取按钮元素
    var myButton = document.getElementById("myButton");
    
    // 给按钮添加点击事件处理程序
    // 当按钮被点击时,点击事件的 Event 对象将被传递给事件处理程序
    myButton.addEventListener("click", function (event) {
      // 检查事件类型
      if (event.type === "click") {
        alert("Button was clicked!");
      }
    });
  • event.clientXevent.clientY

    获取光标相对于浏览器可见窗口左上角的位置 (鼠标事件的鼠标指针的 X 和 Y 坐标值)。

    js
    // <h1>鼠标位置示例</h1>
    // <p>请将鼠标移动到页面中以查看其坐标。</p>
    // <p id="coords"></p>
    
    const coordsEl = document.getElementById("coords");
    // 使用 addEventListener() 方法来监听 mousemove 事件
    // 当鼠标指针在页面上移动时,该事件被触发,并且事件处理程序函数获取鼠标指针的位置,并将其显示在 HTML 文档中
    document.addEventListener("mousemove", (event) => {
      const x = event.clientX;
      const y = event.clientY;
      coordsEl.textContent = `当前鼠标坐标:(${x}, ${y})`;
    });
  • event.offsetXevent.offsetY

    获取光标相对于当前 DOM 元素左上角的位置。当鼠标在事件目标元素内移动时,这些值会随之改变。如果鼠标在事件目标元素外部,则 offsetXoffsetY 的值将为 undefined

    js
    // <div id="box" style="background-color: red; width: 200px; height: 200px;"></div>
    
    const box = document.getElementById("box");
    box.addEventListener("mousemove", (event) => {
      // 当鼠标在红色的<div>元素内移动时,控制台将输出鼠标指针相对于<div>元素左上角的偏移量
      // 这些值可以用于在鼠标事件的处理函数中执行相应的计算,以便进行特定的动态效果
      console.log(`X轴偏移量:${event.offsetX},Y轴偏移量:${event.offsetY}`);
    });
  • event.key

    • 用户按下的键盘键的值
    • 现在不提倡使用 keyCode

key 和 keyCode

  1. event.key 属性

    该属性是表示键盘事件对应的实际字符值。对于字母和数字键,它返回字符本身,对于符号键,它返回对应的符号,例如 event.key 可以返回 "a","B","1","!","$" 等等。

    此外,event.key 还可以返回一些特殊键的名称,例如 "Enter"、"ArrowUp"、"Escape" 等等。这个属性值不受键盘布局或其他设置的影响,可以方便地处理各种不同的键盘输入。

    js
    document.addEventListener("keydown", (event) => {
      console.log(`按下了键:${event.key}`);
    });
  2. event.keyCode 属性:

    该属性是表示键盘事件对应的键码值。键码值是一个整数,代表了按下的键在键盘上的位置和编号。不同的键盘布局可能会导致不同的键码值,例如数字键盘和常规键盘的键码值可能不同。

    event.keyCode 在过去被广泛使用,但现在已被逐渐废弃。因为它在不同的浏览器和设备上有不同的表现,而且不支持非 ASCII 字符。

    js
    document.addEventListener("keydown", (event) => {
      console.log(`按下的键码值:${event.keyCode}`);
    });

总结,event.key 是更好的选择,因为它提供了一个更具语义的方式来表示按下的键。而 event.keyCode 作为一个历史遗留属性,已经不被推荐使用。

案例联系 - 评论回车发布
  • 需求:按下回车键盘,可以发布信息
  • 分析:
    • 用到按下键盘事件 keydown 或者 keyup 都可以
    • 如果用户按下的是回车键盘,则发布信息
    • 让留言信息模块显示,把拿到的数据渲染到对应标签内部
html
css
js

环境对象

  1. 环境对象 this 是什么?
    • 它代表着当前函数运行时所处的环境
  2. 判断 this 指向的粗略规则是什么?
    • 【谁调用,this 就是谁】
  • 环境对象:指的是函数内部特殊的变量 this,它代表着当前函数运行时所处的环境
  • 作用:弄清楚 this 的指向,可以让我们代码更简洁
    • 函数的调用方式不同,this 指代的对象也不同
    • **【谁调用,this 就是谁】**是判断 this 指向的粗略规则
    • 直接调用函数,其实相当于是 window. 函数,所以 this 指代 window

JavaScript 中的环境对象 this 是指当前函数执行的上下文。每个函数都有一个关联的 this 值,它在函数内部使用时表示当前函数所在的上下文对象。this 值可以是全局对象、当前函数所属的对象或者是一个新对象。

当函数被调用时,会自动创建一个 this 上下文对象,这个上下文对象绑定到函数的执行过程中。this 值的实际值取决于函数的调用方式和执行环境。

  1. 全局上下文中的 this:在全局上下文中,this 指向全局对象 window。在浏览器环境中,它是 window 对象;在 Node.js 环境中,它是 global 对象。
  2. 方法中的 this:在一个对象上调用一个方法时,方法内部的 this 值指向当前对象。例如,假设有一个名为 person 的对象,其中有一个名为 name 的方法,则在该方法中调用 this 将返回 person 对象。
  3. 构造函数中的 this:构造函数的 this 指向正在被构造的实例对象。
  4. 通过 call()apply() 方法调用的函数中的 thiscall()apply() 方法能够让一个非 this 上下文的函数以某个对象的上下文来执行。在调用函数时,可以传递一个对象作为 call()apply() 方法的参数,以代替函数内部的 this

综上所述,this 的值是在函数被调用时动态确定的。在编写代码时,要准确理解函数被调用时的上下文,并正确使用 this 值。


在全局作用域中,this 指向全局对象,对于浏览器中的 JavaScript,这个全局对象是 window。在函数内部,this 的值取决于函数被调用的方式。以下是 this 的一些常见用法和值:

  1. 函数作为全局函数被调用时,this 指向全局对象。

    js
    function myFunction() {
      console.log(this); // window
    }
    
    myFunction();
  2. 函数作为某个对象的方法被调用时,this 指向该对象。

    js
    const myObj = {
      myMethod() {
        console.log(this);
      },
    };
    
    myObj.myMethod(); // myObj
  3. 使用 callapply 方法调用函数时,第一个参数指定 this 的值。

    js
    function myFunction() {
      console.log(this);
    }
    
    const myObj = {name: "John"};
    
    myFunction.call(myObj); // myObj
  4. 当使用箭头函数时,this 指向箭头函数定义时的上下文,而不是运行时的上下文。

    js
    const myObj = {
      myMethod() {
        const myArrowFunc = () => {
          console.log(this);
        };
        myArrowFunc();
      },
    };
    
    myObj.myMethod(); // myObj

回调函数

  1. 回调函数
    • 把函数当做另外一个函数的参数传递,这个函数就叫回调函数
    • 回调函数本质还是函数,只不过把它当成参数使用
    • 使用匿名函数做为回调函数比较常见
  • 如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数。
  • 简单理解:当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数。
  • 通常,回调函数用于异步编程中,例如在处理用户输入或从服务器获取数据时。

在 JS 中,每个函数都是一个对象,并且可以作为参数传递给其他函数,这就为回调函数的实现提供了基础。

javascript
function foo(callback) {
  // do something...
  callback();
}

function bar() {
  console.log("Hello World");
}

// 函数 bar() 作为回调函数,在函数 foo() 中被当做参数传递
// 当 foo() 执行完之后,会自动调用 bar() 函数
foo(bar); // 输出:Hello World

回调函数不仅可以被用于简单的异步操作,还可以在函数中使用条件语句来判断是否执行回调函数。

javascript
// add() 函数中判断了传入的参数 callback 是否为函数,如果是则调用回调函数并将结果传递给它
function add(num1, num2, callback) {
  let sum = num1 + num2;
  if (typeof callback === "function") {
    callback(sum);
  }
}

add(1, 2, function (result) {
  console.log("The result is " + result);
}); // 输出:The result is 3
js
// fetchData 函数模拟了从服务器获取数据的过程,它在 2 秒后返回一个对象
function fetchData(callback) {
  setTimeout(function () {
    const data = {name: "John", age: 30};
    callback(data);
  }, 2000);
}

function processData(data) {
  console.log("Name:", data.name);
  console.log("Age:", data.age);
}

// 将 processData 函数作为参数传递给 fetchData 函数,这就是回调函数
// 在 fetchData 函数完成后,它将调用回调函数并将获取到的数据作为参数传递给它
fetchData(processData);

当用户单击按钮时,可以使用回调函数来处理该事件。

js
const button = document.querySelector("button");

// 将一个匿名函数作为回调函数传递给 addEventListener 函数,以便在用户单击按钮时调用该函数
button.addEventListener("click", function () {
  console.log("Button clicked");
});

综合案例 - Tab 栏切换

  • 需求:鼠标经过不同的选项卡,底部可以显示 不同的内容。
  • 分析:
    • 主要核心是类的切换,设定一个当前类,可以让当前元素高亮
    • 鼠标经过当前选项卡,先移除其余元素身上的当前类,而只给当前元素添加类,
    • 注意,当前类只能有一个
html
css
js

作业

点击随机显示图片

html
css
js

同意协议作业

html
css
js

验证码倒计时

html
css
js

显示隐藏密码

html
css
js

小米密码框

html
css
js

手风琴效果

html
css
js